package com.example.propertyanim;

import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.Activity;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {

	private static final String TAG = MainActivity.class.getSimpleName();

	private ValueAnimator mValueAnimator;

	private int mWidth, mHeight;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mWidth = getResources().getDimensionPixelOffset(R.dimen.bezier_view_width);
		mHeight = getResources().getDimensionPixelOffset(R.dimen.bezier_view_height);
		Log.v(TAG, "width=" + mWidth + ", height = " + mHeight);

		final Button button = (Button) findViewById(R.id.button);
		button.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				mValueAnimator.start();
			}
		});

		mValueAnimator = ValueAnimator.ofObject(new BezierEvaluator(), new PointF(0, 0), new PointF(mWidth, mHeight));
		mValueAnimator.setDuration(2000);
		mValueAnimator.addUpdateListener(new AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				PointF pointF = (PointF) animation.getAnimatedValue();
				button.setX(pointF.x);
				button.setY(pointF.y);
			}
		});
		mValueAnimator.setTarget(button);
		mValueAnimator.setRepeatCount(1);
		mValueAnimator.setRepeatMode(ValueAnimator.REVERSE);
	}

	/**
	 * B(t) = P0 * (1-t) * (1-t) * (1-t) + 3 * P1 * t * (1-t) * (1-t) + 3 * P2 * t * t * (1-t) + P3 * t * t * t
	 * */
	private class BezierEvaluator implements TypeEvaluator<PointF> {

		@Override
		public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
			final float t = fraction;
			float oneMinusT = 1.0f - t;

			PointF point0 = (PointF) startValue;

			PointF point1 = new PointF();
			point1.set(mWidth, 0);

			PointF point2 = new PointF();
			point2.set(0, mHeight);

			PointF point3 = (PointF) endValue;

			PointF point = new PointF();
			point.x = oneMinusT * oneMinusT * oneMinusT * (point0.x) + 3 * oneMinusT * oneMinusT * t * (point1.x) + 3 * oneMinusT * t * t * (point2.x) + t * t * t * (point3.x);
			point.y = oneMinusT * oneMinusT * oneMinusT * (point0.y) + 3 * oneMinusT * oneMinusT * t * (point1.y) + 3 * oneMinusT * t * t * (point2.y) + t * t * t * (point3.y);

			return point;
		}
	}

}
